using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ACME.Northwind.DataTransfer;
using ACME.Northwind.Service.Interfaces;
using System.Reflection;
using System.Configuration;

namespace ACME.Northwind.Service.IOCExtensions
{
	/// <summary>
	/// Used to create and return an implementation of a DTO
	/// </summary>
	/// <typeparam name="T">The requested DTO</typeparam>
	internal partial class ProxyFactory<T> where T : IDTO
	{
		public static IPersistableService<T> _instance = null;
		public static IService<T> _instanceReadOnly = null;

		/// <summary>
		/// Gets a DTO implementation
		/// </summary>
		public static IPersistableService<T> GetProxy()
		{
			if (_instance == null)
			{
				string ProxyAssembly = ConfigurationManager.AppSettings["ProxyAssembly"];
				Assembly assembly = Assembly.Load(ProxyAssembly);
				if (assembly == null)
					throw new ApplicationException("Proxy Assembly " + ProxyAssembly + " does not exist");
				List<Type> genericTypes = assembly.GetCreatableObjectImplementsInterface(typeof(IProxyFactory<T>));
				if (genericTypes.Count > 0)
				{
					Type[] typeArgs = { typeof(T) };
					Type makeme = genericTypes[0].MakeGenericType(typeArgs);
					object proxyObject = Activator.CreateInstance(makeme);
					IProxyFactory<T> myProxy = (IProxyFactory<T>)proxyObject;
					_instance = myProxy.GetProxy();
				}
				else
					throw new ApplicationException("Proxy Assembly " + ProxyAssembly + " does not implement a type that inherits from IProxyFactory<T>");
			}
			return _instance;
		}

		/// <summary>
		/// Gets a DTO implementation
		/// </summary>
		public static IService<T> GetReadOnlyProxy()
		{
			if (_instanceReadOnly == null)
			{
				string ProxyAssembly = ConfigurationManager.AppSettings["ProxyAssembly"];
				Assembly assembly = Assembly.Load(ProxyAssembly);
				if (assembly == null)
					throw new ApplicationException("Proxy Assembly " + ProxyAssembly + " does not exist");
				List<Type> genericTypes = assembly.GetCreatableObjectImplementsInterface(typeof(IProxyFactory<T>));
				if (genericTypes.Count > 0)
				{
					Type[] typeArgs = { typeof(T) };
					Type makeme = genericTypes[0].MakeGenericType(typeArgs);
					object proxyObject = Activator.CreateInstance(makeme);
					IProxyFactory<T> myProxy = (IProxyFactory<T>)proxyObject;
					_instanceReadOnly = myProxy.GetReadOnlyProxy();
				}
				else
					throw new ApplicationException("Proxy Assembly " + ProxyAssembly + " does not implement a type that inherits from IProxyFactory<T>");
			}
			return _instanceReadOnly;
		}

	}
}
